/* Standard includes. */
#include <stdio.h>

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"

#include "util.h"

#include "smf.h"

#include "timer.h"

/*debug printf*/
#define TAG_SMFTEST                        "SMFTEST"
#define DebugPrint_SMFTest(fmt,...)        printWithTimestamp(TAG_SMFTEST,fmt, ##__VA_ARGS__) // 带时间戳
// #define DebugPrint_SMFTest(fmt)           printf("%s:%s\r\n", TAG_SMFTEST, fmt) // 不带时间戳    


#define mainSMF_TASK_PRIORITY    ( tskIDLE_PRIORITY + 2 )

/*函数申明*/
// 状态实现的声明
static void s0_entry(void *obj);
static void s0_run(void *obj);
static void s0_exit(void *obj);

static void s1_entry(void *obj);
static void s1_run(void *obj);
static void s1_exit(void *obj);

static void s2_entry(void *obj);
static void s2_run(void *obj);
static void s2_exit(void *obj);

static void prvMainSMFTask( void * pvParameters );

/* 定义状态枚举 */
enum demo_state {
    S0,
    S1,
    S2
};

/* 用户定义的对象，必须包含 smf_ctx 结构体作为第一个成员 */
struct s_object {
    struct smf_ctx ctx; // 状态机上下文
    // 其他状态特定的数据可以在这里添加
};

/* 状态表 */
static const struct smf_state demo_states[] = {
    [S0] = SMF_CREATE_STATE(s0_entry, s0_run, s0_exit),
    [S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit),
    [S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit)
};


/* 状态 S0 的实现 */
static void s0_entry(void *obj) {
    DebugPrint_SMFTest("Entering State 0\n");
}

static void s0_run(void *obj) {
    DebugPrint_SMFTest("State 0 running\n");
    // 转换到状态 S1
    smf_set_state(SMF_CTX(obj), &demo_states[S1]);
}

static void s0_exit(void *obj) {
    DebugPrint_SMFTest("Exiting State 0\n");
}

/* 状态 S1 的实现 */
static void s1_entry(void *obj) {
    DebugPrint_SMFTest("Entering State 1\n");
}

static void s1_run(void *obj) {
    DebugPrint_SMFTest("State 1 running\n");
    // 转换到状态 S2
    smf_set_state(SMF_CTX(obj), &demo_states[S2]);
}

static void s1_exit(void *obj) {
    DebugPrint_SMFTest("Exiting State 1\n");
}

/* 状态 S2 的实现 */
static void s2_entry(void *obj) {
    DebugPrint_SMFTest("Entering State 2\n");
}

static void s2_run(void *obj) {
    DebugPrint_SMFTest("State 2 running\n");
    // 转换回状态 S0
    smf_set_state(SMF_CTX(obj), &demo_states[S0]);
}

static void s2_exit(void *obj) {
    DebugPrint_SMFTest("Exiting State 2\n");
}

/* 应用程序主函数 */
// void main_smftest(void) {
//     struct s_object obj; // 创建状态机对象
    
//     /* Start the tasks and timer running. */
//     vTaskStartScheduler();


//     /* 设置初始状态为 S0 */
//     smf_set_initial(SMF_CTX(&obj), &demo_states[S0]);

//     /* 运行状态机 */
//     while (1) {
//         int32_t ret;
//         ret = smf_run_state(SMF_CTX(&obj));
//         if (ret) {
//             DebugPrint_SMFTest("State machine terminated with return code: %d\n", ret);
//             break;
//         }
//         DebugPrint_SMFTest("delay 1s\n");
//         Timer_Time_Delay( 1000 );   // 延时1秒简单的延时，以便观察状态转换
//         DebugPrint_SMFTest("delay end\n");
//     }

//     // return 0;
// }

void main_smftest(){
        // const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS;

    /* Create the queue. */
    // xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );

    DebugPrint_SMFTest( "main_smftest start\n" );
    // DebugPrint_Blink( "configMINIMAL_STACK_SIZE=%d\n", configMINIMAL_STACK_SIZE);


    /* Start the two tasks as described in the comments at the top of this
        * file. */
    xTaskCreate( prvMainSMFTask,             /* The function that implements the task. */
                "SMF",                            /* The text name assigned to the task - for debug only as it is not used by the kernel. */
                configMINIMAL_STACK_SIZE,        /* The size of the stack to allocate to the task. */
                NULL,                            /* The parameter passed to the task - not used in this simple case. */
                mainSMF_TASK_PRIORITY, /* The priority assigned to the task. */
                NULL );                          /* The task handle is not required, so NULL is passed. */


        /* Start the tasks and timer running. */
        vTaskStartScheduler();

    /* If all is well, the scheduler will now be running, and the following
     * line will never be reached.  If the following line does execute, then
     * there was insufficient FreeRTOS heap memory available for the idle and/or
     * timer tasks	to be created.  See the memory management section on the
     * FreeRTOS web site for more details.  NOTE: This demo uses static allocation
     * for the idle and timer tasks so this line should never execute. */
    for( ; ; )
    {
    }
}

/*----------test report 类型测试-------------------------*/

typedef enum 
{
    NO_REPORT            = 0x0,
    MOUSE_REPORT         = 0x1,
    KEYBOARD_REPORT      = 0x2,
    MULTIMEDA_REPORT     = 0x4,

}_ReportTest_;

typedef union {
    _ReportTest_ report_test;
    uint32_t aligned;
} ReportTest_t;


/* Structure for sending mouse data */
typedef struct _Mouse_Report_
{
    uint8_t click;                            /* Click button status. 
                                             * Oth bit is used for Left click, 
                                             * 1st bit is used for Right Click and 
                                             * 2nd bit is used for middle click 
                                             * 3rd and 4th bit is used for user definedclick */
    int8_t x;                                 /* Delta x movement */
    int8_t y;                                 /* Delta y movement */
    int8_t zwheel;                            /* Delta Vertical movement */
    int8_t hwheel;                            /* Delta Horizontal movement */
}Mouse_Report;

/* Structure for sending keyboard data */
typedef struct _Keyboard_Report_
{
    uint8_t mkey;                              /* Modifier key */
    uint8_t keylength_used;                    /* Number of key used in the key code*/
}Keyboard_Report;

/* Structure which encapsulate all the above structure */
typedef struct _Report_
{
    Mouse_Report            mouse_report;         /* Structure for sending mouse report */
    Keyboard_Report         keyboard_report;      /* Structure for sending keyboard report */
}Report;
// 变量声明
ReportTest_t type;

Report report = {
    .mouse_report.click = 1,
    .mouse_report.x = 21,
    .mouse_report.y = 22,
    .mouse_report.zwheel = 23,
    .mouse_report.hwheel = 24,
    .keyboard_report.mkey = 1,
    .keyboard_report.keylength_used = 1
    };
static void test_report_callback(void *type, Report *report){
    // enum ReportTest_t * const report_type = (void *) type;
    ReportTest_t * const report_type = (ReportTest_t *) type;
    /* 类型测试 */
    DebugPrint_SMFTest("Report Test: %d\n", *(ReportTest*)type);
    switch(report_type->report_test){
        case MOUSE_REPORT:
            DebugPrint_SMFTest("Mouse Report: %d, %d, %d, %d, %d\n", report->mouse_report.click, report->mouse_report.x, report->mouse_report.y, report->mouse_report.zwheel, report->mouse_report.hwheel);
            break;
        case KEYBOARD_REPORT:
            DebugPrint_SMFTest("Keyboard Report: %d, %d\n", report->keyboard_report.mkey, report->keyboard_report.keylength_used);
            break;
        default:
            break;
    }
}
/*------------------------------------------------------------*/

static void prvMainSMFTask( void * pvParameters )
{
    // uint32_t ulReceivedValue;
    struct s_object obj; // 创建状态机对象
    smf_set_initial(SMF_CTX(&obj), &demo_states[S0]);

    /* Prevent the compiler warning about the unused parameter. */
    // ( void ) pvParameters;

    /* test report 类型测试*/
     type.report_test = MOUSE_REPORT;
    sendReportTest((ReportTest *)&type, &report, (void *)test_report_callback);

    for( ; ; )
    {
        int32_t ret;
        ret = smf_run_state(SMF_CTX(&obj));
        if (ret) {
            DebugPrint_SMFTest("State machine terminated with return code: %d\n", ret);
            break;
        }
        vTaskDelay( (1000) );   // 延时1秒简单的延时，以便观察状态转换
    }
}
